package data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Random;
import java.util.TreeMap;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;

import models.OrderModel;
import search.OrderSearchEngine;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;

public class OrderData {
	
	private static Random rand = new Random();
	private static int max = 99999;
	private static int min = 10000;
	
	private static Objectify ofy;

	private static Cache cache = null;

	private static String prefix = "orderData_";

	private static boolean isRegisted = false;

	private int limit = 20;

	private int page = 1;

	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	private static void init() {
		if (!isRegisted) {
			try {
				ObjectifyService.register(OrderModel.class);
			} catch (Exception e) {
				// e.printStackTrace();
			}

			try {
				cache = CacheManager.getInstance().getCacheFactory()
						.createCache(Collections.emptyMap());
			} catch (CacheException e) {
				// e.printStackTrace();
			}

			isRegisted = true;
		}
		ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
		ofy = ObjectifyService.begin(opts);

	}

	public OrderData() {
		init();
	}

	public ArrayList<OrderModel> list() {
		ArrayList<OrderModel> list = new ArrayList<OrderModel>();

		int start = (page - 1) * limit;
		Query<OrderModel> q = ofy.query(OrderModel.class).limit(limit)
				.offset(start);
		for (OrderModel geo : q) {
			list.add(geo);
		}

		return list;
	}

	@SuppressWarnings("unchecked")
	public static void insert(OrderModel order) {
		init();
		if (cache != null) {
			cache.put(prefix + order.getOrderId(), order);
		}
		ofy.put(order);
		OrderSearchEngine.update(order);
	}

	@SuppressWarnings("unchecked")
	public static OrderModel getOrder(String id) {
		init();
		OrderModel order = new OrderModel();
		if (cache != null && cache.containsKey(prefix + id)) {
			order = (OrderModel) cache.get(prefix + id);
		} else {
			try {
				order = ofy.get(new Key<OrderModel>(OrderModel.class, id));
				cache.put(prefix + id, order);
			} catch (Exception e) {
				order = null;
			}
		}
		return order;
	}

	public ArrayList<OrderModel> getOrderByWard(String ward) {
		ArrayList<OrderModel> list = new ArrayList<OrderModel>();
		Query<OrderModel> q = ofy.query(OrderModel.class)
				.filter("shipWard", ward).filter("status", 1);
		for (OrderModel order : q) {
			list.add(order);
		}
		return list;
	}

	public ArrayList<OrderModel> getOrderByUser(String username) {
		ArrayList<OrderModel> list = new ArrayList<OrderModel>();
		Query<OrderModel> q = ofy.query(OrderModel.class).filter("username",
				username);
		for (OrderModel order : q) {
			list.add(order);
		}
		return list;
	}

	public ArrayList<OrderModel> searchOrderByUser(String username,
			int totalFrom, int totalTo, Date fromDate, Date toDate) {
		ArrayList<OrderModel> list = new ArrayList<OrderModel>();
		Query<OrderModel> q = null;
		int filterType = 0;
		ofy.query(OrderModel.class);
		if (username != null && !username.isEmpty()) {
			q = ofy.query(OrderModel.class).filter("username", username);
		}
		if (fromDate != null && toDate != null) {
			filterType = 1;
		} else {
			filterType = 2;
		}
		if (filterType == 1) {
			q = q.filter("orderDate >", fromDate).filter("orderDate <", toDate);
			if (q != null && q.count() > 0) {
				if (totalFrom > 0 || totalFrom > 0) {
					for (OrderModel order : q) {
						if (order.getTotalPrice() >= totalFrom
								&& order.getTotalPrice() <= totalTo) {
							list.add(order);
						}
					}
				} else {
					for (OrderModel order : q) {
						list.add(order);
					}
				}
			}
		} else if (filterType == 2) {
			q = q.filter("totalPrice >=", totalFrom).filter("totalPrice <=",
					totalTo);
			if (q != null && q.count() > 0) {
				for (OrderModel order : q) {
					list.add(order);
				}
			}
		}
		return list;
	}
	
	public static TreeMap<String, Integer> getProductReturn(String returnCoordina)
	{
		String[] arrReturnOrder = returnCoordina.split("\\*");
		TreeMap<String, Integer> productReturn = new TreeMap<String, Integer>();
		for (int i = 0; i < arrReturnOrder.length; i++) {
			String[] arrReturnProduct = arrReturnOrder[i].split("-");
			productReturn.put(arrReturnProduct[0], Integer.parseInt(arrReturnProduct[1]));
		}
		return productReturn;
	}
	
	public static String getOrderRandomId(String dealId) {
		StringBuilder strId = null;
		init();		
		OrderModel obj = new OrderModel();
		boolean done = false;
		while (!done) {
			strId = new StringBuilder();
			int randomNum = rand.nextInt(max - min + 1) + min;
			strId.append(dealId + "-" + randomNum);
			try {
				obj = ofy.get(new Key<OrderModel>(OrderModel.class, strId
						.toString()));
				if (obj != null && obj.getOrderId().length() > 0) {
					done = false;
				} else {
					done = true;
				}
			} catch (NotFoundException e) {
				done = true;
			} catch (Exception e) {
				System.out.println("Error : ");
				e.printStackTrace();
				done = false;
			}
		}
		return strId.toString();
	}
}
